package com.lzc.springPart.aop.advisor;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

public class AspectAndAdvisor {
    public static void main(String[] args) {

        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean(Aspect1.class);
        context.registerBean(Advisor1.class);
        // bean工厂后置处理器
        context.registerBean(ConfigurationClassPostProcessor.class);
        // AOP->bean后置处理器AnnotationAwareAspectJAutoProxyCreator
        /**
         * 其中有两个方法：
         *      findEligibleAdvisors(Target.class, name) 找到所有匹配的advisor
         *      wrapIfNecessary 内部调用findEligibleAdvisors如果返回不为null 则需要创建代理
         */
        context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);

        context.refresh();
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

    }

    static class target1{
        public void foo(){
            System.out.println("foo");
        }
    }

    static class target2{
        public void bar(){
            System.out.println("bar");
        }
    }

    @Aspect
    static class Aspect1{
        @Before("execution(* foo())")
        public void before(){
            System.out.println("before");
        }
    }

    @Configuration
    static class Advisor1{
        @Bean
        public Advisor advisor(MethodInterceptor advice){
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            pointcut.setExpression("execution(* bar())");
            return new DefaultPointcutAdvisor(pointcut,advice);
        }


        @Bean
        public MethodInterceptor methodInterceptor(){
            return new MethodInterceptor() {
                @Override
                public Object invoke(MethodInvocation invocation) throws Throwable {
                    System.out.println("advisor before");
                    invocation.proceed();
                    return null;
                }
            };
        }
    }
}
